﻿using LearnMAUI2.Models;

namespace LearnMAUI2.Services;

public class TodayImageStorage : ITodayImageStorage
{
    private readonly IPreferenceStorage _preferenceStorage;

    //偏好存储只适用于非常小的内容存储，KB-几MB级别
    public static readonly string FullStartDateKey = nameof(TodayImageStorage) +
    "." + nameof(TodayImage.FullStartDate);

    public static readonly string ExpiresAtKey =
        nameof(TodayImageStorage) + "." + nameof(TodayImage.ExpiresAt);

    public static readonly string CopyrightKey =
        nameof(TodayImageStorage) + "." + nameof(TodayImage.Copyright);
    //图片二进制数据使用sqlite存储，存文件或键值对数据库仍然是最优解
    public static readonly string CopyrightLinkKey = nameof(TodayImageStorage) +
        "." + nameof(TodayImage.CopyrightLink);

    //适用于偏好存储的默认值（偏好存储通常会带默认值）

    public const string FullStartDateDefault = "201901010700";

    public static readonly DateTime ExpiresAtDefault = new(2019, 1, 2, 7, 0, 0);

    public const string CopyrightDefault =
        "Salt field province vietnam work (© Quangpraha/Pixabay)";

    public const string CopyrightLinkDefault =
        "https://pixabay.com/photos/salt-field-province-vietnam-work-3344508/";

    //作为嵌入式资源的图片，用于默认情况下的第一次显示
    public const string FileName = "thedevision.bin";

    //存放文件使用的sqlite文件路径
    public static readonly string TodayImagePath =
    Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder
            .LocalApplicationData), FileName);

    public TodayImageStorage(IPreferenceStorage preferenceStorage)
    {
        _preferenceStorage = preferenceStorage;
    }
    public async Task<TodayImage> GetTodayImageAsync(bool includingImageStream)
    {
        //从Preferences读取图片信息
        var todayImage = new TodayImage
        {
            FullStartDate =
        _preferenceStorage.Get(FullStartDateKey, FullStartDateDefault),
            ExpiresAt = _preferenceStorage.Get(ExpiresAtKey, ExpiresAtDefault),
            Copyright = _preferenceStorage.Get(CopyrightKey, CopyrightDefault),
            CopyrightLink = _preferenceStorage.Get(CopyrightLinkKey,
        CopyrightLinkDefault)
        };
        //准备一个内嵌的图片用作启动，起美观作用
        if (!File.Exists(TodayImagePath))
        {
            await using var imageAssetFileStream =
                new FileStream(TodayImagePath, FileMode.Create) ??
                throw new NullReferenceException("Null file stream.");
            //
            await using var imageAssetStream =
                typeof(TodayImageStorage).Assembly.GetManifestResourceStream(
                    FileName) ??
                throw new NullReferenceException(
                    "Null manifest resource stream");
            await imageAssetStream.CopyToAsync(imageAssetFileStream);
        }
        if (!includingImageStream)
        {
            return todayImage;
        }
        //流，支持读写，类似回转寿司，不知道怎么来的，只能送过来的时候拿走，所以只能读写
        //只有内存流能变成二进制数组，所以才必须有文件流->内存流->二进制的过程（因为内存本质上就是字节数组）
        var imageMemoryStream = new MemoryStream();
        await using var imageFileStream =
            new FileStream(TodayImagePath, FileMode.Open);
        await imageFileStream.CopyToAsync(imageMemoryStream);
        todayImage.ImageBytes = imageMemoryStream.ToArray();

        return todayImage;
    }

    public async Task SaveTodayImageAsync(TodayImage todayImage, bool savingExpiresAtOnly)
    {
        _preferenceStorage.Set(ExpiresAtKey, todayImage.ExpiresAt);
        if (savingExpiresAtOnly) return;
        if (todayImage.ImageBytes == null)
            throw new ArgumentNullException($"Null image bytes.", nameof(todayImage));

        _preferenceStorage.Set(FullStartDateDefault, todayImage.FullStartDate);
        _preferenceStorage.Set(CopyrightKey, todayImage.Copyright);
        _preferenceStorage.Set(CopyrightLinkKey, todayImage.CopyrightLink);

        await using var imageFileStream = new FileStream(TodayImagePath, FileMode.Create);
        await imageFileStream.WriteAsync(todayImage.ImageBytes, 0,
            todayImage.ImageBytes.Length);
    }
}
